package com.example.demo.responseBodyAdvice.demo5.controller;

import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson.JSON;
import com.example.demo.excel.util.ExcelUtil;
import com.example.demo.responseBodyAdvice.demo5.db.entity.Student;
import com.example.demo.responseBodyAdvice.demo5.db.repository.StudentRepository;
import com.example.demo.responseBodyAdvice.demo5.util.*;
import com.example.demo.util.ResultUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by jeff on 15/10/23.
 */
@Api(tags = {"ResponseBodyAdvice使用（敏感信息处理使用实体类中字段注解）"})
@RestController
@RequestMapping("/student")
public class StudentController {

    @Autowired
    private StudentRepository studentRepository;
    @Autowired
    private StudentService studentService;

    @NeedEncrypt
    @NeedDecrypt
    @ApiOperation(value = "保存数据（传参过来自己加密,返回值解密）")
    @PostMapping("/save")
    public Object encryptResponse(@RequestBody Student student) {
        Student save = studentRepository.save(student);
        System.out.println("===传参加密结果==" + student);
        return ResultUtil.success("data", save);
    }

    @NeedDecrypt
    @ApiOperation(value = "根据id查询（返回值解密）")
    @GetMapping("/{id}")
    public Object findUserById(@PathVariable("id") Integer id) {
        return ResultUtil.success("data", studentRepository.findById(id));
    }

    @Sensitive
    @ApiOperation(value = "查询所有（返回值解密并脱敏处理）")
    @GetMapping("/all")
    public Object findAllUser() {
        return ResultUtil.success("data", studentRepository.findAll());
    }

    //只传需要更新的值，把需要更新的值set进去
    @NeedEncrypt
    @NeedDecrypt
    @ApiOperation(value = "编辑数据（传参过来自己加密，返回值解密）")
    @PostMapping("/edit")
    public Object editEncryptResponse(@RequestBody Student student) {
        System.out.println("===传参加密结果==" + student);
        Student studentedit = studentRepository.findById(student.getId()).get();
        if (student.getAge() != null && !student.getAge().isEmpty()) {
            studentedit.setAge(student.getAge());
        }
        if (student.getIdcard() != null && !student.getIdcard().isEmpty()) {
            studentedit.setIdcard(student.getIdcard());
        }
        if (student.getSfzjh() != null && !student.getSfzjh().isEmpty()) {
            studentedit.setSfzjh(student.getSfzjh());
        }
        if (student.getName() != null && !student.getName().isEmpty()) {
            studentedit.setName(student.getName());
        }
        if (student.getSex() != null && !student.getSex().isEmpty()) {
            studentedit.setSex(student.getSex());
        }
        if (student.getXh() != null && !student.getXh().isEmpty()) {
            studentedit.setXh(student.getXh());
        }

        studentRepository.save(studentedit);
        return ResultUtil.success("data", studentedit);
    }

    /**
     * 文件下载并且失败的时候返回json（默认失败了会返回一个有部分数据的Excel）
     *
     * @since 2.1.1
     */
    //先查询出数据，对查询的数据list进行解密
    @ApiOperation(value = "导出数据---解密但不脱敏")
    @GetMapping("downloadFailedUsingJson")
    public void downloadFailedUsingJson(HttpServletResponse response) throws IOException {
        List<Student> list = studentRepository.findAll();
        DecryptAspect.decrypt(list);
        // 这里注意 有同学反应使用swagger 会导致各种问题，请直接用浏览器或者用postman
        try {
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
            String fileName = URLEncoder.encode("解密数据", "UTF-8").replaceAll("\\+", "%20");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
            // 这里需要设置不关闭流
            EasyExcel.write(response.getOutputStream(), Student.class).autoCloseStream(Boolean.FALSE).sheet("模板")
                    .doWrite(list);
        } catch (Exception e) {
            // 重置response
            response.reset();
            response.setContentType("application/json");
            response.setCharacterEncoding("utf-8");
            Map<String, String> map = new HashMap<>();
            map.put("status", "failure");
            map.put("message", "下载文件失败" + e.getMessage());
            response.getWriter().println(JSON.toJSONString(map));
        }
    }

    //先查询出数据，对查询的数据list进行解密并脱敏处理
    @ApiOperation(value = "导出数据---解密且脱敏")
    @GetMapping("downloadFailedUsingJson1")
    public void downloadFailedUsingJson1(HttpServletResponse response) throws IOException {
        List<Student> list = studentRepository.findAll();
        SensitiveAspect.decrypt(list);
        // 这里注意 有同学反应使用swagger 会导致各种问题，请直接用浏览器或者用postman
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
        String fileName = URLEncoder.encode("脱敏数据", "UTF-8").replaceAll("\\+", "%20");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
        EasyExcel.write(response.getOutputStream(), Student.class).sheet("模板").doWrite(list);
    }

    @ApiOperation(value = "导出模板")
    @GetMapping(value = "/exportStudentTemplate")
    @ResponseBody
    public void exportTemplate(HttpServletRequest req, HttpServletResponse resp) {
        try {
            // fileName Excel文件名称 ----名称中文的会乱码，前端写死覆盖名称
            String fileName = "student" + System.currentTimeMillis();

            // handers Excel列标题(数组)
            String[] header = {"*学生姓名", "性别", "身份证", "身份证2", "学号", "年龄"};

            // downData 下拉框数据(数组)
            List<String[]> list = new ArrayList<String[]>();
            // downRows 下拉列的序号(数组,序号从0开始)
            List<Integer> listi = new ArrayList<Integer>();

            String text = "填表说明：\r\n" + "1、红色部分为必填，请您务必填写；\r\n" + "2、绿色部分为选填项，您可以根据用户信息酌情填写；\r\n"
                    + "3、为了您顺利、准确导入数据请使用网站导出的原始模板。";

            // listred 需加红的列
            List<Integer> listred = new ArrayList<Integer>();
            listred.add(0);
            listred.add(1);
            listred.add(2);
            listred.add(3);

            // textRows 需转换为text格式的列 ----身份证手机号之类的需要
            List<Integer> textRows = new ArrayList<Integer>();
            textRows.add(3);

            // 性别--具有下拉框
            List<String> keySetxb = new ArrayList<String>();
            keySetxb.add("男");
            keySetxb.add("女");
            String[] xingbie = keySetxb.toArray(new String[keySetxb.size()]);
            list.add(xingbie);
            listi.add(1);

            ExcelUtil.createExcelTemplate(resp, fileName, header, list, listi, text, listred, textRows);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //先读取数据，对需要保存的数据list进行加密
    @ApiOperation(value = "批量导入")
    @PostMapping(value = "/import")
    public void importData(@RequestBody MultipartFile file, HttpServletResponse response) throws IOException {
        Map<String, List<Student>> dataMap = studentService.importExcel(file);
        List<Student> liste = null;
        liste = dataMap.get("liste");
        if (liste != null && liste.size() > 0) {
            // 这里注意 有同学反应使用swagger 会导致各种问题，请直接用浏览器或者用postman
            try {
                response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
                response.setCharacterEncoding("utf-8");
                // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
                String fileName = URLEncoder.encode("错误数据", "UTF-8").replaceAll("\\+", "%20");
                response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
                // 这里需要设置不关闭流
                EasyExcel.write(response.getOutputStream(), Student.class).autoCloseStream(Boolean.FALSE).sheet("模板")
                        .doWrite(liste);
            } catch (Exception e) {
                // 重置response
                response.reset();
                response.setContentType("application/json");
                response.setCharacterEncoding("utf-8");
                Map<String, String> map = new HashMap<>();
                map.put("status", "failure");
                map.put("message", "下载文件失败" + e.getMessage());
                response.getWriter().println(JSON.toJSONString(map));
            }
        }
    }
}
